package com.seari.custody.component;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import com.google.api.client.util.Lists;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 推送消息的微信平台
 */
@Slf4j
@Component
public class WeChatMessagePush {

    @Value("${weChat.messagePush.url}")
    private String weChatMessagePushUrl;
    @Value("${weChat.messagePush.key}")
    private String weChatMessagePushKey;
    private ThreadLocal<Map> paramsThread = new ThreadLocal<>();

    @Retryable(value = {Exception.class}, maxAttempts = 3, backoff = @Backoff(delay = 5000L, multiplier = 1))
    public void pushMessage(String message, Map<String, Object> params) {
        String sign = genSign(params);
        params.put("sign", sign);
        paramsThread.set(params);
        HttpUtil.post(weChatMessagePushUrl, params);
        paramsThread.remove();
    }

    @Recover
    public void recover(Exception e) {
        Map map = paramsThread.get();
        paramsThread.remove();

        log.error(map.toString() + "补偿机制"+e.getMessage());
    }

    /**
     * 生成签名
     * 第一步：设所有发送或者接收到的数据为集合M，将集合M内非空参数值的参数按照参数名ASCII码从小到大排序（字典序），使用URL键值对的格式（即key1=value1&key2=value2…）拼接成字符串stringA。
     * 特别注意以下重要规则：
     * ◆ 参数名ASCII码从小到大排序（字典序）；
     * ◆ 如果参数的值为空不参与签名；
     * ◆ 参数名区分大小写；
     * ◆ sign参数不参与签名，将生成的签名与该sign值作校验；
     * ◆ 接口可能增加字段，验证签名时必须支持增加的扩展字段；
     * 第二步：在stringA最后拼接上key得到stringSignTemp字符串。
     * 第三步：对stringSignTemp进行MD5运算，再将得到的字符串所有字符转换为大写，得到sign值signValue。
     *
     * @param params
     * @return
     */

    private String genSign(Map<String, Object> params) {
        ArrayList<String> paramsList = Lists.newArrayList();
        Set set = params.keySet();
        Object[] arr = set.toArray();
        Arrays.sort(arr);
        for (Object key : arr) {
            Object value = params.get(key);
            if (!Strings.isNullOrEmpty(String.valueOf(value))) {
                paramsList.add(String.format("%s=%s", key, value));
            }
        }
        paramsList.add(String.format("%s=%s", "key", weChatMessagePushKey));

        String sign = Joiner.on("&").skipNulls().join(paramsList);

        sign = SecureUtil.md5(sign).toUpperCase();

        return sign;
    }

    public static void main(String[] args) {
        HashMap<String, String> newHashMap = Maps.newHashMap();
        newHashMap.put("cell", "17712367458");
        newHashMap.put("projectNo", "12");
        WeChatMessagePush weChatMessagePush = new WeChatMessagePush();


    }
}
